package org.cb.core;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import org.cb.gui.MainGUI;

/**
 * 
 * @author Fsig
 * 
 * Testing OCR.
 * Of sorts...
 * 
 * I will try to make a array of images which will
 * be compared to the captured area of the screen.
 * 
 * If a certain image fits then the images ID or string
 * etc will be added to the return array.
 * 
 * Possibly add tolerance to allow for the font changes.
 * 
 * If this works we will be able to get a array of strings
 * or id's back to correspond to letters.
 * 
 * If we get this far we can then use the matched point of
 * each letter to calculate which order they are in.
 *
 */
public class FsigOCR {
	private static int count = 26;
	private static BufferedImage[] tt = new BufferedImage[count];
	private static BufferedImage[] ttC = new BufferedImage[count];
	
	private static Point[] pArray = new Point[count];
	private static int[] sArray = new int[count];
	private static int[] cArray = new int[count];
	
	private static String[] lArray = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
	private static String[] lArrayC = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
	
	private static int removeMe = 0;
	
	/**
	 * Load all our default letters.
	 */
	public static void loadLetters(){
		for(int i = 0; i < count; i++){
			tt[i] = loadImage("ttShadows/" + i + ".png");
			ttC[i] = loadImage("ttShadowsCap/" + i + ".png");
		}
		
		MainGUI.info("Loaded TT shadows.");
	}
	
	private static BufferedImage loadImage(String ref) {
		try {
			return ImageIO.read(new File(ref));
		}catch(Exception e) {e.printStackTrace();}
		return null;
	}
	
	/**
	 * Check the letters within a certain rectangle.
	 * 
	 * @param r
	 * @throws InterruptedException
	 */
	public static String checkLetters(Rectangle r, int tolerance) throws InterruptedException{
		BufferedImage src = Global.getTheCanvas().getImage(r);
		int count = 0;
		
		for(int i = 0; i < tt.length; i++){
			Point p = FindImage(src,tt[i],new Color(255,0,255),tolerance,0,0);
			
			if(p != null){
				MainGUI.log("Found!: " + p + " letter: " + i);
				pArray[count] = p;
				sArray[count] = i;
				cArray[count] = -1;
				count++;
			}
			
		}
		
		for(int i = 0; i < ttC.length; i++){
			Point p = FindImage(src,ttC[i],new Color(255,0,255),tolerance,0,0);
			
			if(p != null){
				MainGUI.log("Found!: " + p + "  cap letter: " + i);
				pArray[count] = p;
				sArray[count] = i;
				cArray[count] = i;
				count++;
			}
		}
		
		for(int i = 0; i < pArray.length; i++){
			Point ps = null;
			
			if(pArray[i] != null){		
				ps = FindImage(src,tt[sArray[i]],
						new Color(255,0,255),
						tolerance,
						pArray[i].x - 3, 
						0);
			}
			
			if(ps != null){
				MainGUI.log("Found!: " + ps + " second letter: " + sArray[i]);
				pArray[count] = ps;
				sArray[count] = sArray[i];
				cArray[count] = -1;
				count++;
			}
		}
		
		//We have all the letters now lets put them in order and make real words.
		return sortArrays();
	}
	
	/**
	 * This will sort our arrays into the correct order
	 * and return the letters.
	 * 
	 * @return String
	 */
	public static String sortArrays() throws InterruptedException{
		String yourWord = "";
		
		for(int i = 0; i < sArray.length; i++){
			String s = getClosest(pArray);
			if(s != null){
				yourWord += s;
				pArray[removeMe] = null;
			}
		}
		
		return yourWord;
	}
	
	/**
	 * This will return the closest letter going
	 * by the points.
	 * 
	 * @param p
	 * @return String
	 */
	public static String getClosest(Point[] p) throws InterruptedException{
		String closest = "";
		int nearest = 9999;

		for(int i = 0; i < p.length; i++){
			if(p[i] != null && p[i].distance(new Point(1,1)) < nearest){
				nearest = (int) p[i].distance(new Point(1,1));
				if(cArray[i] != -1)
					closest = " " + lArrayC[cArray[i]];
				else
					closest = lArray[sArray[i]];
				
				removeMe = i;
			}
		}
		
		return closest;
	}
	
	/**
	 * Attempt to find a letter within a image
	 * 
	 * @param src
	 * @param toFind
	 * @param text
	 * @return
	 * @throws InterruptedException
	 */
	public static Point FindImage(BufferedImage src, BufferedImage toFind, Color text1, int tolerance, int startX, int startY) throws InterruptedException {
		if(src == null || toFind == null){
			return null;
		}
		
		for(int y = startY; y <= (src.getHeight() - toFind.getHeight()) - 1; y++) {
			for(int x = startX; x <= (src.getWidth() - toFind.getWidth()) - 1; x++) {
				if(compareImage(src, toFind, x, y, text1, tolerance))
					return new Point(x, y);
			}
		}

		return null;
	}
	
	/**
	 * Compare the images and return true or false.
	 * 
	 * @param src
	 * @param toFind
	 * @param x
	 * @param y
	 * @param text
	 * @return boolean
	 */
	public static boolean compareImage(BufferedImage src, BufferedImage toFind, int x, int y, Color background, int tolerance) throws InterruptedException{
		int sclr = 0;
		int fclr = 0;
		
		Color c;
		Color cc;
		
		for(int y2 = 0; y2 <= toFind.getHeight() -1; y2++) {
			for(int x2 = 0; x2 <= toFind.getWidth() -1; x2++) {
				fclr = toFind.getRGB(x2, y2);
				c = new Color(fclr);
				
				if(fclr != background.getRGB()) {
					sclr = src.getRGB(x + x2, y + y2);
					cc = new Color(sclr);
					
					if(ColourBot.similarColors(c, cc, tolerance)){
						//Colour matches
					}else{
						return false;
					}
				}else{
					sclr = src.getRGB(x + x2, y + y2);
					cc = new Color(sclr);
					
					if(ColourBot.similarColors(c, cc, tolerance)){
						return false;
					}else{
						//Colour doesn't match, no wrong letters ;)
					}
				}
			}
		}
		return true;
	}

}
